package de.bastian.hinterleitner.tools;

import java.util.ArrayList;
import java.util.Collections;

import de.hijacksoft.wyc.R;

import android.content.Context;

public class EntrySorter {

	public static final int SORT_BY_ID = -1;
	public static final int SORT_BY_NAME = 0;
	public static final int SORT_BY_AMOUNT = 1;
	public static final int SORT_BY_DATE = 2;
	public static final int SORT_BY_CATEGORY = 3;

	private String currency;

	private static EntrySorter singleton = null;
	private Context context;

	public static EntrySorter getSingleton(Context c) {
		if (singleton == null)
			singleton = new EntrySorter(c);
		singleton.context = c;
		return singleton;
	}

	private EntrySorter(Context c) {
		currency = c.getString(R.string.currency);
	}

	public ArrayList<Entry> sortBy(ArrayList<Entry> list, String string) {
		ArrayList<StringEntry> namelist = new ArrayList<StringEntry>();
		for (Entry e : list) {
			namelist.add(new StringEntry(e, string));
		}
		Collections.sort(namelist);
		return new ArrayList<Entry>(namelist);
	}

	public ArrayList<Entry> sortBy(ArrayList<Entry> list, int sorting) {
		switch (sorting) {
		case SORT_BY_ID:
			ArrayList<IDEntry> idlist = new ArrayList<IDEntry>();
			for (Entry e : list) {
				idlist.add(new IDEntry(e));
			}
			Collections.sort(idlist);
			return new ArrayList<Entry>(idlist);
		case SORT_BY_NAME:
			ArrayList<NameEntry> namelist = new ArrayList<NameEntry>();
			for (Entry e : list) {
				namelist.add(new NameEntry(e));
			}
			Collections.sort(namelist);
			return new ArrayList<Entry>(namelist);
		case SORT_BY_AMOUNT:
			ArrayList<AmountEntry> amountlist = new ArrayList<AmountEntry>();
			for (Entry e : list) {
				amountlist.add(new AmountEntry(e));
			}
			Collections.sort(amountlist);
			return new ArrayList<Entry>(amountlist);
		case SORT_BY_DATE:
			ArrayList<DateEntry> datelist = new ArrayList<DateEntry>();
			for (Entry e : list) {
				datelist.add(new DateEntry(e));
			}
			Collections.sort(datelist);
			return new ArrayList<Entry>(datelist);
		case SORT_BY_CATEGORY:
			ArrayList<CategoryEntry> catlist = new ArrayList<CategoryEntry>();
			for (Entry e : list) {
				catlist.add(new CategoryEntry(e));
			}
			Collections.sort(catlist);
			return new ArrayList<Entry>(catlist);
		default:
			return list;
		}
	}

	private class IDEntry extends Entry implements Comparable<IDEntry> {

		public IDEntry(Entry e) {
			super(e);
		}

		@Override
		public int compareTo(IDEntry another) {
			return getId() - another.getId();
		}
	}

	private class NameEntry extends Entry implements Comparable<NameEntry> {

		public NameEntry(Entry e) {
			super(e);
		}

		@Override
		public int compareTo(NameEntry another) {
			return getName().compareTo(another.getName());
		}
	}

	private class AmountEntry extends Entry implements Comparable<AmountEntry> {

		public AmountEntry(Entry e) {
			super(e);
		}

		@Override
		public int compareTo(AmountEntry another) {
			double value = getValueAs(currency, context);
			double anotherValue = another.getValueAs(currency, context);
			
			if (value < 0 && anotherValue > 0)
				return 1;
			if(value > 0 && anotherValue < 0)
				return -1;
			if(value == anotherValue)
				return 0;
			
			return (int) (100 * (Math.abs(anotherValue) - Math.abs(value)));
		}
	}

	private class CategoryEntry extends Entry implements
			Comparable<CategoryEntry> {

		public CategoryEntry(Entry e) {
			super(e);
		}

		@Override
		public int compareTo(CategoryEntry another) {
			return getCategory().compareTo(another.getCategory());
		}
	}

	private class DateEntry extends Entry implements Comparable<DateEntry> {

		public DateEntry(Entry e) {
			super(e);
		}

		@Override
		public int compareTo(DateEntry another) {
			if (getYear() == another.getYear()) {
				if (getMonth() == another.getMonth()) {
					if (getDay() == another.getDay()) {
						return (int) (100 * (another.getValueAs(currency,
								context) - getValueAs(currency, context)));
					} else {
						return another.getDay() - getDay();
					}
				} else {
					return another.getMonth() - getMonth();
				}
			} else {
				return another.getYear() - getYear();
			}
		}
	}

	private class StringEntry extends Entry implements Comparable<StringEntry> {

		private final String COMPARE_STRING;

		public StringEntry(Entry e, String compareString) {
			super(e);
			COMPARE_STRING = compareString;
		}

		@Override
		public int compareTo(StringEntry another) {
			int result = (int) (100 * (Helper.similarity(another.getName(),
					COMPARE_STRING) - Helper.similarity(getName(),
					COMPARE_STRING)));
			if (result == 0) {
				if (getYear() == another.getYear()) {
					if (getMonth() == another.getMonth()) {
						if (getDay() == another.getDay()) {
							result = (int) (100 * (another.getValueAs(currency,
									context) - getValueAs(currency, context)));
						} else {
							result = another.getDay() - getDay();
						}
					} else {
						result = another.getMonth() - getMonth();
					}
				} else {
					result = another.getYear() - getYear();
				}
			}
			return result;
		}
	}

}
